package com.mhtool.json;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.mhtool.framework.common.exception.BizRuntimeException;

import java.io.IOException;
import java.util.List;

/**
 * @since 8.0.0
 */
public abstract class JacksonUtils {

    private static boolean isEmpty(String s) {
        return null == s || s.isEmpty();
    }
    //	SNAKE_CASE：下划线连接单词 (aa_bb_cc,大小写不分)	ID_AA 找字段 id_-aa
//	UPPER_CAMEL_CASE：驼峰式(AaBbCc) 				ID_AA 找字段 Id_AA
//	LOWER_CAMEL_CASE：驼峰式(AaBbCc)				ID_AA 找字段 id_AA
//	LOWER_CASE：无论什么格式，转换成小写输出			ID_AA 找字段 id_aa
//	KEBAB_CASE： 短横线连接单词(aa-bb-cc)			ID_AA 找字段 id_-aa
    public static <T> T string2Object(String json, Class<T> clazz) {
        return string2Object(json, TypeUtils.constructType(clazz));
    }

    public static <T> T string2Object(String json, JavaType type) {
        if (isEmpty(json)) {
            return null;
        }
        return str2java(json, type);
    }

    public static <T> T string2Object(String json, TypeReference<T> valueTypeRef) {
        return string2Object(json, TypeUtils.constructType(valueTypeRef));
    }
    public static String object2String(Object src) {
        return object2String(src, null);
    }
    public static String object2String(Object src, PropertyNamingStrategy strategy) {
        ObjectMapper mapper = getObjectMapper();
        try {
            if (strategy != null) {
                mapper.setPropertyNamingStrategy(strategy);
            }
            return mapper.writeValueAsString(src);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * json 转 list
     */
    public static <T> List<T> string2List(String json, Class<T> elementClass) {
        if (isEmpty(json)) {
            return null;
        }
        JavaType type = TypeUtils.list(elementClass);
        return string2List(json, type);
    }
    /**
     * json 转 list
     * @param type {@link TypeUtils#list(Class, Class)}
     */
    public static <T> List<T> string2List(String json, JavaType type) {
        if (isEmpty(json)) {
            return null;
        }
        return str2java(json, type);
    }

    private static <T> T str2java(String json, JavaType type) {
        ObjectMapper mapper = getObjectMapper();
        try {
            return mapper.readValue(json, type);
        } catch (JsonParseException e) {
            throw jsonParseException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * json 转 list
     */
    public static <T> List<T> string2List(String json, TypeReference<List<T>> typeReference) {
        return string2List(json, TypeUtils.constructType(typeReference));
    }

    public static <T> T convertValue(Object fromValue, Class<T> toValueType) {
        ObjectMapper mapper = getObjectMapper();
        return mapper.convertValue(fromValue, toValueType);
    }

    private static ObjectMapper getObjectMapper() {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        return mapper;
    }

    private static BizRuntimeException jsonParseException(JsonParseException e) {
        return new BizRuntimeException(400, e.getMessage());
    }
}
